package service

// post.go
// 对 Post进行的操作

import (
	"errors"
	"fmt"
	"gforum/global"
	"gforum/model"
	"gorm.io/gorm"
	"strings"
)

// GetUserPostsByID get all posts by user id
func GetUserPostsByID(id string, query model.Pagination) (*[]model.Post, error) {
	var posts []model.Post
	err := global.Db.
		Where("author_id = ?", id).
		Offset((query.Page - 1) * query.Size).
		Limit(query.Size).
		Find(&posts).Error
	if err != nil {
		return nil, err
	}

	return &posts, nil
}

// PostTo 将 PostContent 提交到数据库，并返回 Post
func PostTo(content model.PostContent) (*model.Post, error) {
	post := &model.Post{
		PostContent: content,
	}

	err := global.Db.Create(&post).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, ErrRecordNotFound
	} else if err != nil {
		return nil, err
	}

	return post, nil
}

// GetPostsByID 根据 post ID 从数据库中读取一整个 Post instance
func GetPostsByID(userID string) (*model.Post, error) {
	var post model.Post
	err := global.Db.Where("id = ?", userID).First(&post).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, ErrRecordNotFound
	} else if err != nil {
		return nil, err
	}

	return &post, nil
}

// UpdatePost 根据 post ID 更新 PostContent, 并返回更新后的 Post instance
func UpdatePost(id string, content model.PostEdit) (*model.Post, error) {
	result := global.Db.Model(&model.Post{}).Where("id = ?", id).Updates(content)
	if result.Error != nil {
		return nil, result.Error
	}
	if result.RowsAffected == 0 {
		return nil, ErrRecordNotFound
	}

	var updatedPost model.Post
	err := global.Db.Where("id = ?", id).First(&updatedPost).Error
	if err != nil {
		return nil, err
	}

	return &updatedPost, nil
}

// DeletePostByID 根据 post ID 删除 Post
func DeletePostByID(postID string) error {
	result := global.Db.Where("id = ?", postID).Delete(&model.Post{}, postID)

	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return ErrRecordNotFound
	}

	return nil
}

// GetAllPosts get all posts whit query param
func GetAllPosts(query model.AllPostsPagination) (*[]model.Post, error) {
	var posts []model.Post
	db := global.Db

	// topic
	if query.Topic != "all" {
		db = db.Model(&model.Post{}).Where("topic = ?", query.Topic)
	}

	// sort
	if query.Sort == "hot" {
		db = db.Order("likes DESC")
	} else {
		db = db.Order("created_at DESC")
	}

	err := db.
		Offset((query.Page - 1) * query.Size).
		Limit(query.Size).
		Find(&posts).Error
	if err != nil {
		return nil, err
	}

	return &posts, nil
}

// GetSearchResult return search results depend on query
func GetSearchResult(query model.SearchPagination) (*[]model.Post, error) {
	var posts []model.Post
	db := global.Db

	// topic
	if query.Topic != "all" {
		db = db.Model(&model.Post{}).Where("topic = ?", query.Topic)
	}

	// 处理搜索关键词 Q
	terms := strings.Fields(query.Q)
	for _, term := range terms {
		pattern := fmt.Sprintf("%%%s%%", term)
		db = db.Where("(title LIKE ? OR content LIKE ?)", pattern, pattern)
	}

	if query.Sort == "relevance" && len(terms) > 0 {
		// 按相关度排序
		// 构造相关度打分表达式：title 命中 +2，content 命中 +1
		express := make([]string, 0, len(terms)*2)
		args := make([]interface{}, 0, len(terms)*2)
		for _, term := range terms {
			pat := fmt.Sprintf("%%%s%%", term)
			express = append(express, "CASE WHEN title LIKE ? THEN 2 ELSE 0 END")
			args = append(args, pat)
			express = append(express, "CASE WHEN content LIKE ? THEN 1 ELSE 0 END")
			args = append(args, pat)
		}
		orderSQL := strings.Join(express, " + ") + " DESC"
		db = db.Order(gorm.Expr(orderSQL, args...))
	} else {
		// 按创建时间倒序
		db = db.Order("created_at DESC")
	}

	offset := (query.Page - 1) * query.Size
	db = db.Offset(offset).Limit(query.Size)

	if err := db.Find(&posts).Error; err != nil {
		return nil, err
	}

	return &posts, nil
}
